package org.bsscheduler;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author tblackstone
 */
public class EventList {

    // Using a SortedSet for events - provides a synchronized sorted list with
    // no duplicates
    private SortedSet<Event> events;
    private String user;

    public EventList(String username) {
        events = Collections.synchronizedSortedSet(
                new TreeSet<Event>((Comparator) new EventComparator()));
        user = username;
    }

    public String getUsername() {
        return user;
    }

    /**
     * Adds an event to a this user's event list.  Also stores the event in
     * the user's event file and notifies other participants to approve/deny the
     * event.
     * @param newEvent
     */
    public synchronized void addEvent(Event newEvent) {

        Vector<String> participants = newEvent.getParticipants();
        TreeMap<String, String> userList = UsersDB.userList(false);

        events.add(newEvent);

        String messageBody = "You have created new appointment. " +
                "Here are the details:\n\n" +
                "Appointment title: " + newEvent.getTitle() + "\n" +
                "Appointment description: " + newEvent.getDescription() + "\n" +
                "Appointment start: " +
                newEvent.getStartDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                "Appointment end: " +
                newEvent.getEndDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                "Creator: " + newEvent.getCreator() + "\n" +
                "Participants: ";

        if (participants.size() == 0) {
            messageBody += "none\n";
        } else {
            for (String pEmail : participants) {
                messageBody += userList.get(pEmail) +
                        "(" + newEvent.getParticipantStatus(pEmail) + ")" + "\n";
            }
            messageBody += "\nAll of the above participants have also been notified" +
                    " of the appointment.";
        }

        messageBody += "\n\nThank you for using BS Scheduler!\n";

        SendMail.send(newEvent.getCreator(), "Message from Scheduler: " +
                "New Appointment Created!", messageBody);

        // Also add event to participants' lists and send e-mail to them
        for (String p : newEvent.getParticipants()) {
            EventsDB.getEvents(p).addAsParticipant(newEvent);

            messageBody = "You have been invited to an appointment by " +
                    userList.get(newEvent.getCreator()) + ". " +
                    "Here are the details:\n\n" +
                    "Appointment title: " + newEvent.getTitle() + "\n" +
                    "Appointment description: " + newEvent.getDescription() + "\n" +
                    "Appointment start: " +
                    newEvent.getStartDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                    "Appointment end: " +
                    newEvent.getEndDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                    "Creator: " + newEvent.getCreator() + "\n" +
                    "Participants: ";

            if (participants.size() == 0) {
                messageBody += "none\n";
            } else {
                for (String pEmail : participants) {
                    messageBody += userList.get(pEmail) +
                            "(" + newEvent.getParticipantStatus(pEmail) + ")" + "\n";
                }
            }

            messageBody += "\n\nThank you for using BS Scheduler!\n";

            SendMail.send(p, "Message from Scheduler: " +
                    "New Appointment Invite!", messageBody);

        }

        // Save changes to file as backup
        EventsDB.writeEventFile(user);

    }

    /**
     * Adds the given event to this user's list because they were requested to
     * participate. Note that this does not send out any notification or update
     * the user's event file
     * @param event the event to add
     */
    public synchronized void addAsParticipant(Event event) {

        events.remove(event);
        events.add(event);
    }

    public synchronized void cancelEvent(Event event) {

        Vector<String> participants = event.getParticipants();
        removeEvent(event);
        TreeMap<String, String> userList = UsersDB.userList(false);

        String messageBody = "You have cancelled an appointment. " +
                "Here are the details:\n\n" +
                "Appointment title: " + event.getTitle() + "\n" +
                "Appointment description: " + event.getDescription() + "\n" +
                "Appointment start: " +
                event.getStartDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                "Appointment end: " +
                event.getEndDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                "Creator: " + event.getCreator() + "\n" +
                "Participants: ";

        if (participants.size() == 0) {
            messageBody += "none\n";
        } else {
            for (String pEmail : participants) {
                messageBody += userList.get(pEmail) +
                        "(" + event.getParticipantStatus(pEmail) + ")" + "\n";
            }
            messageBody += "\nAll of the above participants have also been notified" +
                    " of the appointment cancellation.";
        }

        messageBody += "\n\nThank you for using BS Scheduler!\n";

        SendMail.send(event.getCreator(), "Message from Scheduler: " +
                "Appointment Cancelled!", messageBody);


        for (String p : event.getParticipants()) {
            EventsDB.getEvents(p).removeEvent(event);

            messageBody = "An appointment you were invited to has been cancelled by " +
                    userList.get(event.getCreator()) + ". " +
                    "Here are the appointment details:\n\n" +
                    "Appointment title: " + event.getTitle() + "\n" +
                    "Appointment description: " + event.getDescription() + "\n" +
                    "Appointment start: " +
                    event.getStartDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                    "Appointment end: " +
                    event.getEndDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                    "Creator: " + event.getCreator() + "\n" +
                    "Participants: ";

            if (participants.size() == 0) {
                messageBody += "none\n";
            } else {
                for (String pEmail : participants) {
                    messageBody += userList.get(pEmail) +
                            "(" + event.getParticipantStatus(pEmail) + ")" + "\n";
                }
            }

            messageBody += "\n\nThank you for using BS Scheduler!\n";

            SendMail.send(p, "Message from Scheduler: " +
                    "Appointment Cancelled!", messageBody);

        }

        // Save changes to file as backup
        EventsDB.writeEventFile(user);
    }

    public synchronized void removeEvent(Event event) {
        events.remove(event);
    }

    public Event getEvent(String uuid) {

        for (Event e : events) {
            if (e.getUUID().equals(uuid)) {
                return e;
            }
        }
        return null;
    }

    /**
     * Update a participant's status
     * @param event the event to update
     * @param status this user's new status
     */
    public synchronized void updateEventStatus(Event event, int status) {

        event.setParticipantStatus(user, status);

        TreeMap<String, String> userList = UsersDB.userList(false);
        Vector<String> participants = event.getParticipants();

        String messageBody = "";

        if (status == Event.CONFIRMED) {
            messageBody += userList.get(user) + " has confirmed to attend " +
                    "the appointment listed below. ";
        } else if (status == Event.DECLINED) {
            messageBody += userList.get(user) + " has declined to attend " +
                    "the appointment listed below. ";
        }
        messageBody += "Here are the appointment details:\n\n" +
                "Appointment title: " + event.getTitle() + "\n" +
                "Appointment description: " + event.getDescription() + "\n" +
                "Appointment start: " +
                event.getStartDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                "Appointment end: " +
                event.getEndDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                "Creator: " + event.getCreator() + "\n" +
                "Participants: ";

        if (participants.size() == 0) {
            messageBody += "none\n";
        } else {
            for (String pEmail : participants) {
                messageBody += userList.get(pEmail) +
                        "(" + event.getParticipantStatus(pEmail) + ")" + "\n";
            }
        }

        messageBody += "\n\nThank you for using BS Scheduler!\n";

        SendMail.send(event.getCreator(), "Message from Scheduler: " +
                "Appointment Participant Status Update!", messageBody);


        for (String p : event.getParticipants()) {

            if (status == Event.CONFIRMED) {
                messageBody = userList.get(user) + " has confirmed to attend " +
                        "the appointment listed below. ";
            } else if (status == Event.DECLINED) {
                messageBody = userList.get(user) + " has declined to attend " +
                        "the appointment listed below. ";
            }
            messageBody += "Here are the appointment details:\n\n" +
                    "Appointment title: " + event.getTitle() + "\n" +
                    "Appointment description: " + event.getDescription() + "\n" +
                    "Appointment start: " +
                    event.getStartDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                    "Appointment end: " +
                    event.getEndDate("EEE, MMM d, yyyy h:mm a") + "\n" +
                    "Creator: " + event.getCreator() + "\n" +
                    "Participants: ";

            if (participants.size() == 0) {
                messageBody += "none\n";
            } else {
                for (String pEmail : participants) {
                    messageBody += userList.get(pEmail) +
                            "(" + event.getParticipantStatus(pEmail) + ")" + "\n";
                }
            }

            messageBody += "\n\nThank you for using BS Scheduler!\n";

            SendMail.send(p, "Message from Scheduler: " +
                    "Appointment Participant Status Update!", messageBody);

        }

        EventsDB.writeEventFile(event.getCreator());

    }

    /**
     * Gets all of the events contained within this EventList. This includes
     * events that this user has been invited to participate in.
     * @return a Date/Time-sorted list of Events
     */
    public SortedSet<Event> getAllEvents() {
        return events;
    }

    /**
     *
     * @param date the day to get events for, in the format 'yyyy-MM-dd'
     * @return an set of the events for the day, ordered by starting time
     */
    public SortedSet<Event> getEventsForDate(String date) {

        TreeSet<Event> dayEvents = new TreeSet<Event>((Comparator) new EventComparator());

        for (Event e : events) {
            String eDate = e.getStartDate("yyyy-MM-dd");

            if (eDate.equals(date)) {
                dayEvents.add(e);
            }

        }

        return dayEvents;
    }

    public SortedSet<Event> getInvitedEvents() {

        TreeSet<Event> invitedEvents = new TreeSet<Event>((Comparator) new EventComparator());

        for (Event e : events) {
            // If this user did not create the event, they must have been invited
            if (!e.getCreator().equals(user)) {
                invitedEvents.add(e);
            }
        }

        return invitedEvents;

    }

    public SortedSet<Event> getPendingEventInvites() {

        TreeSet<Event> invitedEvents = new TreeSet<Event>((Comparator) new EventComparator());

        for (Event e : events) {
            if (e.getParticipantStatus(user).equals("requested")) {
                invitedEvents.add(e);
            }
        }

        return invitedEvents;

    }


    // Comparator class for sorting events by start date/time
    class EventComparator implements Comparator<Event> {

        public int compare(Event arg0, Event arg1) {

            // Events have the same UUID, so are equal
            if (arg0.getUUID().equals(arg1.getUUID())) {
                return 0;
            }

            Date d1 = arg0.getRawStartDate();
            Date d2 = arg1.getRawStartDate();

            if (d1.before(d2)) {
                return -1;
            } else {
                return 1;
            }
        }
    }
}
